'''
Created on 05.03.2011

@author: bstar
'''
from dopplershift.core.containers.mediator import getMediator
from dopplershift.collector.config import XMLCollectorConfig
from dopplershift.core.conf import ConfigNotFound
from twisted.internet import reactor
import json
from dopplershift.core.utils.logger import DSLogging
import logging
from dopplershift.collector.testing.collection import TestCollection
from dopplershift.collector.backends.auth.redis import RedisBasedBackend
from dopplershift.core.app.cline import CommandLineApp

logger = logging.getLogger("TEST")
mediator = getMediator()

class TestManager(CommandLineApp):
    max_workers = 5
    config_class = XMLCollectorConfig
    auth_backend = RedisBasedBackend
    __program__ = 'ds-autotest'
    __description__ = 'Doplershift Collector web site autotesting subsystem'
    __arguments__ = (
                     {
                      'name': '--logLevel',
                      'dest': 'logLevel',
                      'type': str,
                      'help': 'loglevel identify',
                      'default': 'WARNING'
                      },
                     )
    def __init__(self):
        CommandLineApp.__init__(self)
        self._tests = []
        self._workers = []
        self._cnt_workers = 0
        self._config_path = self._args.configfile
        self._errors = 0
        self._warnings = 0
        self._positivity = 0
        self._all = 0
    def run(self):
        d = DSLogging(
                      self._args.logLevel
                      )
        d.twistedObserver()
        reactor.callLater(1, self.start)
        reactor.run()
    def stop(self):
        logger.warning("                                               ")
        logger.warning("Test process finish sucesfully. Statistic info:")
        logger.warning("-----------------------------------------------")
        logger.warning("Succesfully passed: %s"%(self._positivity))
        logger.warning("Errors found: %s"%self._errors)
        logger.warning("Warrnings found: %s"%self._warnings)
        logger.warning("All tests: %s"%self._all)
        logger.warning("-----------------------------------------------")
        reactor.stop()
    def _configLoad(self):
        self._all += 1
        try:
            self._config = self.config_class(self._config_path)
        except ConfigNotFound as e:
            self._errors += 1
            
            logger.error("Config not found on path %s"%self._config_path)
            self.stop()
            return False
        self._positivity += 1
        logger.info("Config loaded succesful")
        mediator.register("CollectorConfig", self._config)
        return True
    def _createTestCollection(self):
        self._test_collection = TestCollection()
        self._all += 1
        self._positivity += 1
        logger.info("Test Collection Initialized")
        return True
    def _testFinished(self, testResult, worker):
        if worker in self._workers:
            self._workers.remove(worker)
        self._positivity += testResult.positiv
        self._errors += testResult.errors
        self._warnings += testResult.warns
        self._all += testResult.positiv + testResult.errors + testResult.warns
        self._getNextTest()
    def _getNextTest(self):
        if len(self._workers) < self.max_workers and len(self._tests) > 0:
            test = self._tests.pop()
            if test is not None:
                self._workers.append(test)
                d = test.runTest()
                d.addCallback(
                          self._testFinished, test
                          )
        if len(self._workers) > 0:
            return
        if len(self._workers) == 0 and len(self._tests) == 0: 
            backend = mediator.get("AuthBackend")
            d = backend.removeAuth(mediator.get("AuthTestId"))
            d.addCallbacks(
                          lambda x: self.stop(),
                          lambda x: self.stop()
                          )
            return
        self._getNextTest()
    def _testCalls(self):
        test = self._test_collection.getNextCallTest()
        while test:
            self._tests.append(test)
            test = self._test_collection.getNextCallTest()
    def _createAuthCollection(self):
        ab = self.auth_backend()
        ab.run()
        mediator.register("AuthBackend", ab)
        return True
    def _createTestAuthConf(self):
        conf = mediator.get("CollectorConfig").get_test_define("auth")
        data = json.loads(conf.text)
        mediator.register("AuthTest", data)
        mediator.register("AuthTestId", hash(conf.text))
        
    def start(self):
        if not self._configLoad(): return
        if not self._createTestCollection(): return
        if not self._createAuthCollection(): return
        self._createTestAuthConf()
        self._testCalls()
        reactor.callLater(
                          5,
                          self._getNextTest
                          )